<template>
  <div class="uploader-container">
    <el-upload
      class="uploader"
      action=""
      :disabled="isUploading"
      :accept="accept"
      :show-file-list="false"
      :on-change="fileChange"
      :style="{ height: size + 'px', width: width + 'px'}"
      :auto-upload="false">
      <template v-if="isUploading">
        <div class="loading-tips flex-center f-14" :style="{ height: size + 'px', width: width + 'px'}">
          <div>
            <div class="pt-16" v-if="type === 'video'">{{percentage + '%'}}</div>
            <div>正在上传...</div>
          </div>
        </div>
      </template>
      <template v-else-if="src">
        <img :src="src" class="media" v-if="type === 'image'" :style="{ height: size + 'px', width: width + 'px'}">
        <video :src="src" class="media" v-else-if="type === 'video'" controls :style="{ height: size + 'px', width: width + 'px'}"></video>
      </template>
      <div v-else class="icon flex-center" :style="{ height: size + 'px', width: width + 'px'}">
        <i class="el-icon-plus uploader-icon"></i>
      </div>
    </el-upload>
    <i class="el-icon-circle-close f-24" @click="del" v-if="src"></i>
  </div>
</template>
<script>
import { getVodToken, getOssToken, getVideoInfo } from '@/api/upload';
import OSS from 'ali-oss';
import { generateFileName } from '@/utils';

export default {
  props: {
    src: String,
    videoId: String,
    duration: [Number, String],
    type: {
      type: String,
      default: 'image', // or video
    },
    size: {
      default: 120,
      type: [String, Number],
    },
  },
  data() {
    return {
      currentSrc: '',
      isUploading: false,
      percentage: 0,
      uploader: null,
      ossClient: null,
    };
  },
  computed: {
    accept() {
      if (this.type === 'image') {
        return 'image/jpeg,image/jpg,image/png';
      }
      return 'audio/mp4,video/mp4';
    },
    width() {
      return this.type === 'image' ? this.size : (16 * this.size) / 9;
    },
  },
  methods: {
    fileChange(fileData) {
      const file = fileData.raw;
      if (this.type === 'video') {
        this.uploadVideo(file);
      } else {
        this.uploadImage(fileData);
      }
    },
    uploadVideo(file) {
      const userData = '{"Vod":{}}';
      if (this.uploader) {
        this.uploader.stopUpload();
        this.percentage = 0;
      }
      this.uploader = this.createUploader();
      this.uploader.addFile(file, null, null, null, userData);
      this.uploader.startUpload();
    },
    async uploadImage(fileData) {
      this.isUploading = true;
      const { name, raw } = fileData;
      const result = await getOssToken();
      const {
        accessKeyId, accessKeySecret, securityToken, region, bucketName, endpoint,
      } = result;
      const fileName = generateFileName(name);
      this.ossClient = new OSS({
        accessKeyId,
        accessKeySecret,
        stsToken: securityToken,
        bucket: bucketName,
        endpoint,
        region,
      });
      const { url } = await this.ossClient.put(fileName, raw);
      this.$emit('update:src', url);
      this.isUploading = false;
    },
    createUploader() {
      const self = this;
      const uploader = new AliyunUpload.Vod({
        userId: '238206294875716357', // 阿里账号ID
        // 添加文件成功
        addFileSuccess(uploadInfo) {
          console.log('addFileSuccess: ' + uploadInfo.file.name);
        },
        // 开始上传
        async onUploadstarted(uploadInfo) {
          self.isUploading = true;
          const result = await getVodToken();
          const { accessKeyId, accessKeySecret, securityToken } = result;
          uploader.setSTSToken(uploadInfo, accessKeyId, accessKeySecret, securityToken);
        },
        // 文件上传成功
        async onUploadSucceed(uploadInfo) {
          const {
            bucket, endpoint, object, videoId,
          } = uploadInfo;
          const vidoeUrl = `${endpoint.slice(0, 8)}${bucket}.${endpoint.slice(8)}/${object}`;
          self.isUploading = false;
          console.log('success', uploadInfo);
          self.$emit('update:src', vidoeUrl);
          self.$emit('update:videoId', videoId);
          setTimeout(async () => {
            const { video } = await getVideoInfo(videoId);
            self.$emit('update:duration', parseInt(video.duration, 10));
            self.$message.success('上传成功');
          }, 2000);
        },
        // 文件上传失败
        onUploadFailed() {
          self.$message.error('上传失败');
          self.isUploading = false;
        },
        // 文件上传进度，单位：字节, 可以在这个函数中拿到上传进度并显示在页面上
        onUploadProgress(uploadInfo, totalSize, progress) {
          self.percentage = Math.ceil(progress * 100);
        },
        // 上传凭证超时
        async onUploadTokenExpired(uploadInfo) {
          self.$message.error('上传凭证超时，正在重新上传');
          const { videoId } = uploadInfo;
          const result = await self.refreshUploadAuth(videoId);
          const { uploadAuth } = result;
          uploader.resumeUploadWithAuth(uploadAuth);
        },
      });
      return uploader;
    },
    del() {
      this.$emit('update:src', '');
      this.$emit('update:videoId', '');
      this.$emit('update:duration', 0);
    },
  },
};
</script>
<style lang="scss" scoped>
  .uploader-container {
    position: relative;
    display: inline-block;
    .uploader {
      ::v-deep .el-upload {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
        height: 100%;
        &:hover {
          border-color: hsl(210, 100%, 63%);
        }
        .icon {
          .uploader-icon {
            font-size: 28px;
            color: #8c939d;
            text-align: center;
          }
        }
        .media {
          display: block;
        }
      }
    }
    .el-icon-circle-close {
      position: absolute;
      right: 0;
      top: 0;
      transform: translate(50%, -50%);
      cursor: pointer;
    }
  }
</style>
